#pragma once

#include <iostream>
#include <cerrno>
// #include "Log.hpp"
#include "Socket.hpp"
#include "Nocopy.hpp"
#include <cstring>
#include <sys/epoll.h>

class Epoller : public Nocopy
{
    static const int size = 128;    
public:
    Epoller()
    {
        _epfd = epoll_create(size);     // 创建 epoll 模型
        if(_epfd == -1)
        {
            lg(Error, "epoll_create error: %s", strerror(errno));
        }
        else
        {
            lg(Info, "epoll_create success, %d", _epfd);
        }
    }
    ~Epoller()
    {
        if(_epfd >= 0) close(_epfd);
    }
public:
    int EpollerWait(struct epoll_event revents[], int num)  //epoll将会把发生的事件赋值到events数组(位图形式)中
    {
        int n = epoll_wait(_epfd, revents, num, _timeout);
        return n;   // 返回已经就绪的文件描述符的个数

    }
    int EpollUpdate(int oper, int sock, uint32_t event)
    {
        // op：哪个操作：EPOLL CTL ADD【添加】 / EPOLL CTL MOD【修改】 / EPOLL CTL DEL【删除】
        // sock：哪个文件描述符fd
        // event：哪些事件
        int n = 0;
        if(oper == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, oper, sock, nullptr);  // 删除就没有事件了，就是 nullptr
            if(n != 0)
            {
                lg(Error, "epoll_ctl delete error");
            }
        }
        else
        {
            // EPOLL CTL ADD【添加】 / EPOLL CTL MOD【修改】 
            struct epoll_event ev;
            ev.events = event;
            ev.data.fd = sock;      // 方便我们后期直到哪一个fd 就绪了

            n = epoll_ctl(_epfd, oper, sock, &ev);
            if(n != 0)
            {
                lg(Error, "epoll_ctl delete error");
            }
        }
        return n;
    }
private:
    int _epfd;
    int _timeout{3000};
};